home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / gr564s.zip / SRC / MS / SPAWNVPQ.C < prev    next >
C/C++ Source or Header  |  1992-09-05  |  2KB  |  115 lines

  1. /* spawnvpq for MS-DOS and OS/2 */
  2.  
  3. /* by Paul Eggert and Frank Whaley */
  4.  
  5.     /* $Id: spawnvpq.c,v 1.5 1992/02/17 23:02:20 eggert Exp $ */
  6.  
  7. #include <errno.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11.  
  12. /*
  13. * Most MS-DOS and OS/2 versions of spawnvp do not
  14. * properly handle arguments with embedded blanks,
  15. * so spawnvpq works around the bug by quoting arguments itself.
  16. * The quoting regime, bizarre as it sounds, is as follows:
  17. *
  18. *    If an argument contains N (>=0) backslashes followed by '"',
  19. *    precede the '"' with an additional N+1 backslashes.
  20. *
  21. *    Surround an argument with '"' if it contains space or tab.
  22. *
  23. *    If an argument contains space or tab and ends with N backslashes,
  24. *    append an additional N backslashes.
  25. */
  26.     int
  27. spawnvpq(int mode, char const *path, char * const *argv)
  28. {
  29.     char *a, **argw, **aw, *b, *buf;
  30.     char * const *av;
  31.     size_t argsize = 0, argvsize;
  32.  
  33.     for (av = argv;  (a = *av++);  ) {
  34.         size_t backslashrun = 0, quotesize = 0;
  35.         char *p = a;
  36.         for (;;) {
  37.             switch (*p++) {
  38.                 case '\t': case ' ':
  39.                     quotesize = 2;
  40.                     /* fall into */
  41.                 case '"':
  42.                     argsize += backslashrun + 1;
  43.                     /* fall into */
  44.                 default:
  45.                     backslashrun = 0;
  46.                     continue;
  47.  
  48.                 case '\\':
  49.                     backslashrun++;
  50.                     continue;
  51.  
  52.                 case 0:
  53.                     if (quotesize)
  54.                         argsize += backslashrun;
  55.                     break;
  56.             }
  57.             break;
  58.         }
  59.         argsize += p - a + quotesize;
  60.     }
  61.  
  62.     argvsize = (av-argv) * sizeof(char*);
  63.     if (!(buf  =  malloc(argvsize + argsize))) {
  64.         errno = E2BIG;
  65.         return -1;
  66.     }
  67.     aw = argw = (char**)buf;
  68.     b = buf + argvsize;
  69.  
  70.     for (av = argv;  (a = *av++);  ) {
  71.         char c;
  72.         int contains_white = strchr(a, ' ') || strchr(a, '\t');
  73.         size_t backslashrun = 0;
  74.         char *p = a;
  75.         *aw++ = b;
  76.         if (contains_white)
  77.             *b++ = '"';
  78.         for (;  ;  *b++ = c) {
  79.             switch ((c = *p++)) {
  80.                 case '\\':
  81.                     backslashrun++;
  82.                     continue;
  83.  
  84.                 case '"':
  85.                     backslashrun++;
  86.                     memset(b, '\\', backslashrun);
  87.                     b += backslashrun;
  88.                     /* fall into */
  89.                 default:
  90.                     backslashrun = 0;
  91.                     continue;
  92.  
  93.                 case 0:
  94.                     break;
  95.             }
  96.             break;
  97.         }
  98.         if (contains_white) {
  99.             memset(b, '\\', backslashrun);
  100.             b += backslashrun;
  101.             *b++ = '"';
  102.         }
  103.         *b++ = 0;
  104.     }
  105.     *aw = 0;
  106.  
  107.     {
  108.         int r = spawnvp(mode, path, argw);
  109.         int e = errno;
  110.         free(buf);
  111.         errno = e;
  112.         return r;
  113.     }
  114. }
  115.